/*   1:    */ package org.intellij.plugins.relaxNG.validation;
/*   2:    */ 
/*   3:    */

import com.intellij.lang.ASTNode;
import com.intellij.lang.annotation.AnnotationHolder;
import com.intellij.lang.annotation.ExternalAnnotator;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.psi.*;
import com.intellij.psi.search.PsiElementProcessor.FindElement;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.xml.*;
import org.intellij.plugins.relaxNG.compact.RncFileType;
import org.intellij.plugins.relaxNG.compact.psi.RncFile;
import org.intellij.plugins.relaxNG.model.resolve.RelaxIncludeIndex;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;

import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/*   4:    */
/*   5:    */
/*   6:    */
/*   7:    */
/*   8:    */
/*   9:    */
/*  10:    */
/*  11:    */
/*  12:    */
/*  13:    */
/*  14:    */
/*  15:    */
/*  16:    */
/*  17:    */
/*  18:    */
/*  19:    */
/*  20:    */
/*  21:    */
/*  22:    */
/*  23:    */
/*  24:    */
/*  25:    */
/*  26:    */
/*  27:    */
/*  28:    */
/*  29:    */
/*  30:    */
/*  31:    */
/*  32:    */
/*  33:    */
/*  34:    */
/*  35:    */
/*  36:    */
/*  37:    */
/*  38:    */
/*  39:    */
/*  40:    */
/*  41:    */
/*  42:    */ 
/*  43:    */ public class RngSchemaValidator
/*  44:    */   extends ExternalAnnotator<MyValidationMessageConsumer, MyValidationMessageConsumer>
/*  45:    */ {
/*  46: 57 */   private static final Logger a = Logger.getInstance(RngSchemaValidator.class.getName());
/*  47:    */   
/*  48:    */   @Nullable
/*  49:    */   public MyValidationMessageConsumer collectInformation(@NotNull final PsiFile paramPsiFile)
/*  50:    */   {
/*  51: 62 */     if (paramPsiFile == null) {
/*  52: 62 */       throw new IllegalArgumentException(String.format("Argument %s for @NotNull parameter of %s.%s must not be null", new Object[] { "0", "org/intellij/plugins/relaxNG/validation/RngSchemaValidator", "collectInformation" }));
/*  53:    */     }
/*  54: 62 */     FileType localFileType = paramPsiFile.getFileType();
/*  55: 63 */     if ((localFileType != StdFileTypes.XML) && (localFileType != RncFileType.getInstance())) {
/*  56: 64 */       return null;
/*  57:    */     }
/*  58: 66 */     XmlFile localXmlFile = (XmlFile)paramPsiFile;
/*  59: 67 */     XmlDocument localXmlDocument = localXmlFile.getDocument();
/*  60: 68 */     if (localXmlDocument == null) {
/*  61: 69 */       return null;
/*  62:    */     }
/*  63: 71 */     if (localFileType == StdFileTypes.XML)
/*  64:    */     {
/*  65: 72 */       localObject = localXmlDocument.getRootTag();
/*  66: 73 */       if (localObject == null) {
/*  67: 74 */         return null;
/*  68:    */       }
/*  69: 76 */       if (!"http://relaxng.org/ns/structure/1.0".equals(((XmlTag)localObject).getNamespace())) {
/*  70: 77 */         return null;
/*  71:    */       }
/*  72:    */     }
/*  73: 80 */     else if ((!ApplicationManager.getApplication().isUnitTestMode()) && (MyErrorFinder.hasError(localXmlFile)))
/*  74:    */     {
/*  75: 81 */       return null;
/*  76:    */     }
/*  77: 84 */     Object localObject = PsiDocumentManager.getInstance(paramPsiFile.getProject()).getDocument(paramPsiFile);
/*  78:    */     
/*  79: 86 */     final MyValidationMessageConsumer localMyValidationMessageConsumer = new MyValidationMessageConsumer();
/*  80: 87 */     DefaultHandler local1 = new DefaultHandler()
/*  81:    */     {
/*  82:    */       public void warning(SAXParseException paramAnonymousSAXParseException)
/*  83:    */       {
/*  84: 90 */         RngSchemaValidator.handleError(paramAnonymousSAXParseException, paramPsiFile, this.val$doc, localMyValidationMessageConsumer.warning());
/*  85:    */       }
/*  86:    */       
/*  87:    */       public void error(SAXParseException paramAnonymousSAXParseException)
/*  88:    */       {
/*  89: 95 */         RngSchemaValidator.handleError(paramAnonymousSAXParseException, paramPsiFile, this.val$doc, localMyValidationMessageConsumer.error());
/*  90:    */       }
/*  91: 98 */     };
/*  92: 99 */     RngParser.parsePattern(paramPsiFile, local1, true);
/*  93:100 */     return localMyValidationMessageConsumer;
/*  94:    */   }
/*  95:    */   
/*  96:    */   @Nullable
/*  97:    */   public MyValidationMessageConsumer doAnnotate(MyValidationMessageConsumer paramMyValidationMessageConsumer)
/*  98:    */   {
/*  99:106 */     return paramMyValidationMessageConsumer;
/* 100:    */   }
/* 101:    */   
/* 102:    */   public void apply(@NotNull PsiFile paramPsiFile, MyValidationMessageConsumer paramMyValidationMessageConsumer, @NotNull AnnotationHolder paramAnnotationHolder)
/* 103:    */   {
/* 104:113 */     if (paramPsiFile == null) {
/* 105:113 */       throw new IllegalArgumentException(String.format("Argument %s for @NotNull parameter of %s.%s must not be null", new Object[] { "0", "org/intellij/plugins/relaxNG/validation/RngSchemaValidator", "apply" }));
/* 106:    */     }
/* 107:113 */     if (paramAnnotationHolder == null) {
/* 108:113 */       throw new IllegalArgumentException(String.format("Argument %s for @NotNull parameter of %s.%s must not be null", new Object[] { "2", "org/intellij/plugins/relaxNG/validation/RngSchemaValidator", "apply" }));
/* 109:    */     }
/* 110:113 */     paramMyValidationMessageConsumer.apply(paramAnnotationHolder);
/* 111:    */   }
/* 112:    */   
/* 113:    */   static class MyValidationMessageConsumer
/* 114:    */   {
/* 115:117 */     List<Pair<PsiElement, String>> errors = new ArrayList();
/* 116:118 */     List<Pair<PsiElement, String>> warnings = new ArrayList();
/* 117:    */     
/* 118:    */     RngSchemaValidator.ValidationMessageConsumer error()
/* 119:    */     {
/* 120:120 */       new RngSchemaValidator.ValidationMessageConsumer()
/* 121:    */       {
/* 122:    */         public void onMessage(PsiElement paramAnonymousPsiElement, String paramAnonymousString)
/* 123:    */         {
/* 124:123 */           RngSchemaValidator.MyValidationMessageConsumer.this.errors.add(Pair.create(paramAnonymousPsiElement, paramAnonymousString));
/* 125:    */         }
/* 126:    */       };
/* 127:    */     }
/* 128:    */     
/* 129:    */     RngSchemaValidator.ValidationMessageConsumer warning()
/* 130:    */     {
/* 131:128 */       new RngSchemaValidator.ValidationMessageConsumer()
/* 132:    */       {
/* 133:    */         public void onMessage(PsiElement paramAnonymousPsiElement, String paramAnonymousString)
/* 134:    */         {
/* 135:131 */           RngSchemaValidator.MyValidationMessageConsumer.this.warnings.add(Pair.create(paramAnonymousPsiElement, paramAnonymousString));
/* 136:    */         }
/* 137:    */       };
/* 138:    */     }
/* 139:    */     
/* 140:    */     void apply(AnnotationHolder paramAnnotationHolder)
/* 141:    */     {
/* 142:136 */       RngSchemaValidator.ErrorMessageConsumer localErrorMessageConsumer = new RngSchemaValidator.ErrorMessageConsumer(paramAnnotationHolder);
/* 143:137 */       RngSchemaValidator.WarningMessageConsumer localWarningMessageConsumer = new RngSchemaValidator.WarningMessageConsumer(paramAnnotationHolder);
/* 144:138 */       for (Iterator localIterator = this.errors.iterator(); localIterator.hasNext();)
/* 145:    */       {
/* 146:138 */         localPair = (Pair)localIterator.next();
/* 147:139 */         localErrorMessageConsumer.onMessage((PsiElement)localPair.first, (String)localPair.second);
/* 148:    */       }
/* 149:    */       Pair localPair;
/* 150:141 */       for (localIterator = this.warnings.iterator(); localIterator.hasNext();)
/* 151:    */       {
/* 152:141 */         localPair = (Pair)localIterator.next();
/* 153:142 */         localWarningMessageConsumer.onMessage((PsiElement)localPair.first, (String)localPair.second);
/* 154:    */       }
/* 155:    */     }
/* 156:    */   }
/* 157:    */   
/* 158:    */   public static void handleError(SAXParseException paramSAXParseException, PsiFile paramPsiFile, Document paramDocument, ValidationMessageConsumer paramValidationMessageConsumer)
/* 159:    */   {
/* 160:148 */     String str = paramSAXParseException.getSystemId();
/* 161:149 */     if (a.isDebugEnabled()) {
/* 162:150 */       a.debug("RNG Schema error: " + paramSAXParseException.getMessage() + " [" + str + "]");
/* 163:    */     }
/* 164:    */     Object localObject1;
/* 165:153 */     if (str != null)
/* 166:    */     {
/* 167:154 */       localObject1 = findVirtualFile(str);
/* 168:155 */       if (!Comparing.equal(localObject1, paramPsiFile.getVirtualFile())) {
/* 169:156 */         return;
/* 170:    */       }
/* 171:    */     }
/* 172:161 */     int i = paramSAXParseException.getLineNumber();
/* 173:    */     Object localObject2;
/* 174:162 */     if (i > 0)
/* 175:    */     {
/* 176:163 */       int j = paramSAXParseException.getColumnNumber();
/* 177:164 */       int k = paramDocument.getLineStartOffset(i - 1);
/* 178:    */       PsiElement localPsiElement;
/* 179:166 */       if (j > 0)
/* 180:    */       {
/* 181:167 */         if (paramPsiFile.getFileType() == RncFileType.getInstance())
/* 182:    */         {
/* 183:168 */           localPsiElement = paramPsiFile.findElementAt(k + j);
/* 184:169 */           if (localPsiElement == null) {
/* 185:170 */             localObject1 = localPsiElement;
/* 186:    */           } else {
/* 187:172 */             localObject1 = paramPsiFile.findElementAt(k + j - 1);
/* 188:    */           }
/* 189:    */         }
/* 190:    */         else
/* 191:    */         {
/* 192:175 */           localObject1 = paramPsiFile.findElementAt(k + j - 2);
/* 193:    */         }
/* 194:    */       }
/* 195:    */       else
/* 196:    */       {
/* 197:178 */         localPsiElement = paramPsiFile.findElementAt(k);
/* 198:179 */         localObject1 = localPsiElement != null ? PsiTreeUtil.nextLeaf(localPsiElement) : null;
/* 199:    */       }
/* 200:    */     }
/* 201:    */     else
/* 202:    */     {
/* 203:182 */       localObject2 = ((XmlFile)paramPsiFile).getDocument();
/* 204:183 */       assert (localObject2 != null);
/* 205:184 */       XmlTag localXmlTag = ((XmlDocument)localObject2).getRootTag();
/* 206:185 */       assert (localXmlTag != null);
/* 207:186 */       localObject1 = localXmlTag.getFirstChild();
/* 208:    */     }
/* 209:190 */     if ((paramPsiFile instanceof RncFile)) {
/* 210:191 */       localObject2 = localObject1;
/* 211:    */     } else {
/* 212:193 */       localObject2 = PsiTreeUtil.getParentOfType((PsiElement)localObject1, new Class[] { XmlAttribute.class, XmlTag.class });
/* 213:    */     }
/* 214:195 */     if ((localObject1 != null) && (localObject2 != null)) {
/* 215:196 */       paramValidationMessageConsumer.onMessage((PsiElement)localObject2, paramSAXParseException.getMessage());
/* 216:    */     } else {
/* 217:198 */       paramValidationMessageConsumer.onMessage(paramPsiFile, paramSAXParseException.getMessage());
/* 218:    */     }
/* 219:    */   }
/* 220:    */   
/* 221:    */   public static VirtualFile findVirtualFile(String paramString)
/* 222:    */   {
/* 223:    */     try
/* 224:    */     {
/* 225:204 */       return VfsUtil.findFileByURL(new URL(paramString));
/* 226:    */     }
/* 227:    */     catch (Exception localException)
/* 228:    */     {
/* 229:206 */       a.warn("Failed to build file from uri <" + paramString + ">", localException);
/* 230:    */     }
/* 231:207 */     return VirtualFileManager.getInstance().findFileByUrl(VfsUtil.fixURLforIDEA(paramString));
/* 232:    */   }
/* 233:    */   
/* 234:    */   public static abstract interface ValidationMessageConsumer
/* 235:    */   {
/* 236:    */     public abstract void onMessage(PsiElement paramPsiElement, String paramString);
/* 237:    */   }
/* 238:    */   
/* 239:    */   private static abstract class MessageConsumerImpl
/* 240:    */     implements RngSchemaValidator.ValidationMessageConsumer
/* 241:    */   {
/* 242:    */     protected final AnnotationHolder myHolder;
/* 243:    */     
/* 244:    */     public MessageConsumerImpl(AnnotationHolder paramAnnotationHolder)
/* 245:    */     {
/* 246:219 */       this.myHolder = paramAnnotationHolder;
/* 247:    */     }
/* 248:    */     
/* 249:    */     public void onMessage(PsiElement paramPsiElement, String paramString)
/* 250:    */     {
/* 251:224 */       ASTNode localASTNode1 = paramPsiElement.getNode();
/* 252:225 */       assert (localASTNode1 != null);
/* 253:    */       ASTNode localASTNode2;
/* 254:227 */       if ((paramPsiElement instanceof XmlAttribute))
/* 255:    */       {
/* 256:228 */         localASTNode2 = XmlChildRole.ATTRIBUTE_NAME_FINDER.findChild(localASTNode1);
/* 257:229 */         createAnnotation(localASTNode2, paramString);
/* 258:    */       }
/* 259:230 */       else if ((paramPsiElement instanceof XmlTag))
/* 260:    */       {
/* 261:231 */         localASTNode2 = XmlChildRole.START_TAG_NAME_FINDER.findChild(localASTNode1);
/* 262:232 */         if (localASTNode2 != null) {
/* 263:233 */           createAnnotation(localASTNode2, paramString);
/* 264:    */         }
/* 265:236 */         ASTNode localASTNode3 = XmlChildRole.CLOSING_TAG_NAME_FINDER.findChild(localASTNode1);
/* 266:237 */         if (localASTNode3 != null) {
/* 267:238 */           createAnnotation(localASTNode3, paramString);
/* 268:    */         }
/* 269:    */       }
/* 270:    */       else
/* 271:    */       {
/* 272:241 */         createAnnotation(localASTNode1, paramString);
/* 273:    */       }
/* 274:    */     }
/* 275:    */     
/* 276:    */     protected abstract void createAnnotation(ASTNode paramASTNode, String paramString);
/* 277:    */   }
/* 278:    */   
/* 279:    */   private static class ErrorMessageConsumer
/* 280:    */     extends RngSchemaValidator.MessageConsumerImpl
/* 281:    */   {
/* 282:    */     @NonNls
/* 283:    */     private static final String a = "missing \"start\" element";
/* 284:    */     private static final String b = "reference to undefined pattern ";
/* 285:    */     
/* 286:    */     public ErrorMessageConsumer(AnnotationHolder paramAnnotationHolder)
/* 287:    */     {
/* 288:254 */       super();
/* 289:    */     }
/* 290:    */     
/* 291:    */     protected void createAnnotation(ASTNode paramASTNode, String paramString)
/* 292:    */     {
/* 293:259 */       if ("missing \"start\" element".equals(paramString))
/* 294:    */       {
/* 295:260 */         PsiFile localPsiFile = paramASTNode.getPsi().getContainingFile();
/* 296:261 */         if ((localPsiFile instanceof XmlFile))
/* 297:    */         {
/* 298:262 */           PsiElementProcessor.FindElement localFindElement = new PsiElementProcessor.FindElement();
/* 299:263 */           RelaxIncludeIndex.processBackwardDependencies((XmlFile)localPsiFile, localFindElement);
/* 300:264 */           if (localFindElement.isFound())
/* 301:    */           {
/* 302:266 */             this.myHolder.createWeakWarningAnnotation(paramASTNode, paramString);
/* 303:267 */             return;
/* 304:    */           }
/* 305:    */         }
/* 306:    */       }
/* 307:270 */       else if ((paramString != null) && (paramString.startsWith("reference to undefined pattern ")))
/* 308:    */       {
/* 309:272 */         return;
/* 310:    */       }
/* 311:274 */       this.myHolder.createErrorAnnotation(paramASTNode, paramString);
/* 312:    */     }
/* 313:    */   }
/* 314:    */   
/* 315:    */   private static class WarningMessageConsumer
/* 316:    */     extends RngSchemaValidator.MessageConsumerImpl
/* 317:    */   {
/* 318:    */     public WarningMessageConsumer(AnnotationHolder paramAnnotationHolder)
/* 319:    */     {
/* 320:281 */       super();
/* 321:    */     }
/* 322:    */     
/* 323:    */     protected void createAnnotation(ASTNode paramASTNode, String paramString)
/* 324:    */     {
/* 325:286 */       this.myHolder.createWarningAnnotation(paramASTNode, paramString);
/* 326:    */     }
/* 327:    */   }
/* 328:    */   
/* 329:    */   private static class MyErrorFinder
/* 330:    */     extends PsiRecursiveElementVisitor
/* 331:    */   {
/* 332:291 */     private static final MyErrorFinder a = new MyErrorFinder();
/* 333:295 */     private static final HasError b = new HasError(null);
/* 334:    */     
/* 335:    */     public void visitErrorElement(PsiErrorElement paramPsiErrorElement)
/* 336:    */     {
/* 337:299 */       throw b;
/* 338:    */     }
/* 339:    */     
/* 340:    */     public static boolean hasError(PsiElement paramPsiElement)
/* 341:    */     {
/* 342:    */       try
/* 343:    */       {
/* 344:304 */         paramPsiElement.accept(a);
/* 345:305 */         return false;
/* 346:    */       }
/* 347:    */       catch (HasError localHasError) {}
/* 348:307 */       return true;
/* 349:    */     }
/* 350:    */     
/* 351:    */     private static final class HasError
/* 352:    */       extends RuntimeException
/* 353:    */     {}
/* 354:    */   }
/* 355:    */ }



/* Location:           E:\idea\

 * Qualified Name:     org.intellij.plugins.relaxNG.validation.RngSchemaValidator

 * JD-Core Version:    0.7.0.1

 */